// 1 导入react
import React from 'react'
import ReactDOM from 'react-dom'

// 引入css文件
import "./index.css"

import img from './img/cat.jpg'



//  
// 高阶组件(HOC Higher-Order Component) 是一个函数接收要包装的组件 返回增强后的组件
// 高阶组件内部创建一个类组件 在这个类组件中提供复用的状态逻辑代码 通过prop将复用的状态传递给被包装组件  WrappedComponent



// 使用步骤
// 1. 创建一个函数, 名称约束以with开头
// 2. 指定函数参数, 参数应该以大学字母开头(作为要渲染的组件)
// 3. 在函数内部创建一个类组件,提供复用的状态逻辑代码,并返回
// 4. 在该组件中, 渲染参数组件,同时将状态通过prop传递给参数组件
// 5. 调用该高阶组件, 传入要增强的组件, 通过返回值拿到增强后的组件,并将其渲染到页面中


// 设置displayName  
// 使用高阶组件存在的问题:得到的两个组件的名称相同
// 原因:默认情况下 React 使用组件名称作为displayName
// 解决方式: 为高阶组件设置displayName 便于调试时区不同的组件
// dispatchName的作用: 用于设置调式信息(React Developer Tools 信息)


// 传递props 
// 问题: props丢失
// 原因: 高阶组件没有往下传递props
// 解决方式: 渲染WrappedComponent时, 将state和this.props 一起传递给组件


// React 组件进阶总结
// 1. 组件通讯是构建React应用必不可少的一环
// 2. props的灵活性让组件更加强大
// 3. 状态提升是React组件的常见模式
// 4. 组件的生命周期有助理解组件的运行过程
// 5. 钩子函数让开发者可以在特定的世纪执行某些功能
// 6. render props模式和高阶组件都可以实现组件状态逻辑复用
// 7. 组件极简模型: (state,props)=>UI




// 创建高阶组件
function withMouse(WrappedComponent) {

    //该组件提供复用的状态逻辑
    class Mouse extends React.Component {

        state = {
            x: 0,
            y: 0
        }

        handlerMouseMove = (e) => {
            this.setState({
                x: e.clientX,
                y: e.clientY
            })
        }

        // 控制鼠标状态的逻辑
        componentDidMount() {
            window.addEventListener('mousemove', this.handlerMouseMove)
        }

        //推荐: 在组件卸载时移除
        componentWillUnmount() {
            window.removeEventListener('mousemove', this.handleMouseMove)
        }
        render() {
            // console.log(this.props)
            return <WrappedComponent {...this.state} {...this.props}></WrappedComponent>
        }

    }
    Mouse.displayName = `WithMouse${getDisplayName(WrappedComponent)}`
    return Mouse
}

// 设置displayName
function getDisplayName(WrappedComponent) {
    return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}


// 测试高阶组件
const Position = props => {
    console.log(props)
    const { x, y } = props
    return (
        < p >
            鼠标当前的位置:
            x: {x},
            y: {y}
        </p >
    )
}


//state=> 对象成员变量
//props=> 方法的入参

// 猫捉老鼠组件
const Cat = props => {
    console.log(props)
    const { x, y } = props
    return <img src={img}
        alt="猫捉老鼠"
        width="200"
        style={{
            position: 'absolute',
            top: y - 50,
            left: x - 100
        }}
    />
}


// 获取增强后的组件
const MousePosition = withMouse(Position)
const MouseCat = withMouse(Cat)



class App extends React.Component {

    render() {
        return (
            <div>
                <h2>高级组件的使用</h2>
                {/* 渲染增强后的组件 */}
                <MousePosition info='坐标' />
                <MouseCat info='cat' />
            </div>
        )
    }
}

//3 渲染react元素
ReactDOM.render(
    <App />,
    document.getElementById('root'))
